<?php
use oxide\http\Request;
use oxide\http\Response;

/**
 * load all required libraries into the system
 */
require_once LIB_DIR . '/oxide/Request.php';
require_once LIB_DIR . '/oxide/Response.php';
require_once APP_DIR . '/library/ActionController.php';
require_once LIB_DIR . '/oxide/Statement.php';
require_once LIB_DIR . '/oxide/Exception.php';
require_once APP_DIR . '/library/Auth.php';
require_once APP_DIR . '/library/Common.php';
require_once APP_DIR . '/library/DataHelper.php';
require_once APP_DIR . '/library/Validator.php';
require_once APP_DIR . '/library/ActionController.php';

/**
 * Front Controller.  
 * 
 * tunnel for all user requests
 * Uses Router and Dispatcher objects to route the request to proper Controller
 * 
 * FrontController is also responsible for final output using Response object.
 * @package yasns
 * @subpackage library
 */
class FrontController
{
	private static
	   $_instance;
	
	public
		$request,
		$response;

	/**
	 * constructor
	 * 
	 * cannot be explicitly created.
	 * controller must be created using getInstance() method instead
	 * @access private 
	 */
	private function __construct()
	{
		session_start();
		
		// only one single copy of instance at a time
		if (self::$_instance !== null) {
			throw new Exception("Front Controller already initialized and started.");
		}
		
		// add request and response objects
		$this->request = new Request();
		$this->response = new Response();
	}
	
	/**
	 * returns the single instance of this object
	 * 
	 * @access public
	 * @return FrontController 
	 */
	public static function getInstance()
	{
		if (self::$_instance === NULL) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}

	/**
	 * starts processing the request
	 * 
	 * this method should be called within the index.php file in the html root folder
	 * @access public
	 * @param void
	 * @return void 
	 */
	public function run()
	{	
		try {
			// attempt to dispatch action to proper action controller
			$this->dispatch($this->request);
		} catch(Exception $e) {
			// default/global excepction handler
			// let error controller handle it.
			require_once  APP_DIR . '/controller/ErrorActionController.php';
			$errorController = new ErrorActionController();
			$errorController->exception = $e;
			$errorController->execute();
		}
	}

	/**
	 * dispatch request to ActionController for execute
	 *
	 * @access public
	 */
	public function dispatch($request)
	{
		// create the action controller using factory method
		$controller = ActionController::make($request, $this->response);
		
		// check if controller available
		// if so execute
		// else through excepiton
		if(!($controller instanceof Command)) {
			throw new Exception('Page not found', 404);
		}
		
		$controller->execute();
	}		  
	
	
	public function __destruct() 
	{
		
	}
}
?>